package com.aqie.manager.service;

import com.aqie.entity.Product;
import com.aqie.entity.enums.ProductStatus;
import com.aqie.manager.error.ErrorEnum;
import com.aqie.manager.repositories.ProductRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.persistence.criteria.*;
import java.math.BigDecimal;

import java.util.ArrayList;

import java.util.Date;
import java.util.List;

/**
 * 产品服务类
 */
@Service
public class ProductService {
    // 日志对象
    private static Logger LOG = LoggerFactory.getLogger(ProductService.class);

    @Autowired
    private ProductRepository repository;

    /**
     * 添加产品
     * @param product
     * @return
     */
    public Product addProduct(Product product){
        LOG.debug("创建产品，参数:{}", product);
        checkProduct(product);
        setDefault(product);
        Product result = repository.save(product);
        LOG.debug("创建产品, 结果:{}", result);
        return result;
    }

    /**
     * 设置默认值
     * 创建时间,更新时间
     * 投资步长，锁定期， 状态
     * @param product
     */
    private void setDefault(Product product) {
        if (product.getCreateAt() == null) {
            product.setCreateAt(new Date());            // java.util.Date
        }
        if (product.getUpdateAt() == null) {
            product.setUpdateAt(new Date());
        }
        if (product.getStepAmount() == null) {
            product.setStepAmount(BigDecimal.ZERO);
        }
        if (product.getLockTerm() == null) {
            product.setLockTerm(0);
        }
        if (product.getStatus() == null) {
            product.setStatus(ProductStatus.AUDITING.name());
        }
    }

    /**
     * 产品参数校验
     * 1.非空数据
     * 2.收益率 0-30
     * 3.投资步长须为整数
     * @param product
     */
    private void checkProduct(Product product) {
        Assert.notNull(product.getId(), ErrorEnum.ID_NOT_NULL.getCode());
        // todo 其他非空校验

        Assert.isTrue(BigDecimal.ZERO.compareTo(product.getRewardRate()) < 0 && BigDecimal.valueOf(30).compareTo(product.getRewardRate()) >= 0,
                ErrorEnum.REWARD_RATE_ERROR.getCode());

        Assert.isTrue(BigDecimal.valueOf(product.getStepAmount().longValue()).compareTo(product.getStepAmount()) == 0,
                ErrorEnum.STEP_AMOUNT_RANGE_ERROR.getCode());
    }

    public Product findOne(String id) {
        Assert.notNull(id, "需要产品编号参数");
        LOG.debug("查询单个产品，id={}", id);

        Product product = repository.findById(id).orElse(null);

        LOG.debug("查询单个产品,结果={}", product);

        return product;
    }

    /**
     * 分页查询商品列表
     *  返回一个分页对象
     * @param idList            传递多个编号
     * @param minRewardRate     最小收益率
     * @param maxRewardRate     最大收益率
     * @param statusList        多个状态
     * @param pageable          分页参数
     * @return
     */
    public Page<Product> query(List<String> idList,
                               BigDecimal minRewardRate, BigDecimal maxRewardRate,
                               List<String> statusList,
                               Pageable pageable) {
        LOG.debug("查询产品,idList={},minRewardRate={},maxRewardRate={},statusList={},pageable={}",
                idList, minRewardRate, maxRewardRate, statusList, pageable);
        Specification<Product> specification = (Specification<Product>) (root, query, cb) -> {
            // 获取编号列
            Expression<String> idCol = root.get("id");
            Expression<BigDecimal> rewardRateCol = root.get("rewardRate");
            Expression<String> statusCol = root.get("status");
            // 断言列表 JPA 相关
            List<Predicate> predicates = new ArrayList<>();
            if (idList != null && idList.size() > 0) {
                predicates.add(idCol.in(idList));
            }
            if (minRewardRate != null && BigDecimal.ZERO.compareTo(minRewardRate) < 0) {
                predicates.add(cb.ge(rewardRateCol, minRewardRate));
            }
            if (maxRewardRate != null && BigDecimal.ZERO.compareTo(maxRewardRate) < 0) {
                predicates.add(cb.le(rewardRateCol, maxRewardRate));
            }
            if (statusList != null && statusList.size() > 0) {
                predicates.add(statusCol.in(statusList));
            }

            query.where(predicates.toArray(new Predicate[0]));
            return null;
        };

        Page<Product> page = repository.findAll(specification, pageable);

        LOG.debug("查询产品,结果={}", page);
        return page;
    }
}
